package com.yonyou.brigade.order_center.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.yonyou.brigade.basic_init.enums.ChannelEnum;
import com.yonyou.brigade.order_center.dao.BriHotelOrderMapper;
import com.yonyou.brigade.order_center.model.*;
import com.yonyou.brigade.order_center.service.IBriHotelOrderService;
import com.yonyou.brigade.order_center.service.IBriHotelRoomService;
import com.yonyou.brigade.order_center.service.IInvoiceRelationshipService;
import com.yonyou.ybzboot.starter.common.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * 酒店订单服务实现类
 *
 * @author jiangzhf@yonyou.com
 * @since 2018-06-14
 */
@Service
public class BriHotelOrderServiceImpl extends ServiceImpl<BriHotelOrderMapper, BriHotelOrder> implements IBriHotelOrderService {
    @Autowired
    private BriHotelOrderMapper briHotelOrderMapper;

    @Autowired
    private IBriHotelRoomService briHotelRoomService;

    @Autowired
    private IInvoiceRelationshipService relationshipService;

    @Override
    public List<CnvHotelOrderDO> getCnvHotelOrderDos(Map<String, String> params, Date beginDate, Date endDate) {
        List<CnvHotelOrderDO> cnvHotelOrderDOList = new ArrayList<>();
        // 根据条件查询所有的订单
        Wrapper<BriHotelOrder> hotelOrderWrapper = new EntityWrapper<>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            hotelOrderWrapper.eq(entry.getKey(), entry.getValue());
        }
        hotelOrderWrapper.between("departure_date", beginDate, endDate);
        hotelOrderWrapper.ne(true,"is_note",1);
        hotelOrderWrapper.eq(true, "public_or_private", "1");
        hotelOrderWrapper.ne(true,"order_no","");
        hotelOrderWrapper.ne(true,"category","");

        List<BriHotelOrder> briHotelOrderList = briHotelOrderMapper.selectList(hotelOrderWrapper);
        ArrayList<String> CompletedOrderStatus = new ArrayList<String>(Arrays.asList("13","14","15","17","20","11","19"));
        if (briHotelOrderList != null &&briHotelOrderList.size() > 0) {
            for (BriHotelOrder briHotelOrder : briHotelOrderList) {
                // 过滤订单状态
                if (StringUtils.isNotBlank(briHotelOrder.getOrderStatus()) && CompletedOrderStatus.contains(briHotelOrder.getOrderStatus())){
                    if (dealWithRefundOrder(briHotelOrder)) {
                        continue;
                    }
                    CnvHotelOrderDO cnvHotelOrderDO = new CnvHotelOrderDO();
                    cnvHotelOrderDO.setOrderNo(briHotelOrder.getOrderNo());
                    cnvHotelOrderDO.setTravelType(briHotelOrder.getTravelType());
                    cnvHotelOrderDO.setPublicOrPrivate(briHotelOrder.getPublicOrPrivate());
                    cnvHotelOrderDO.setIsDomc(briHotelOrder.getIsDomc());
                    cnvHotelOrderDO.setPreiumReason(briHotelOrder.getPreiumReason());
                    cnvHotelOrderDO.setStatusType(briHotelOrder.getStatusType());
                    cnvHotelOrderDO.setCreateBy(briHotelOrder.getCreateBy());
                    cnvHotelOrderDO.setOrderTime(briHotelOrder.getOrderTime());
                    cnvHotelOrderDO.setOrderStatusName(briHotelOrder.getOrderStatusName());
                    cnvHotelOrderDO.setPaymentPrice(briHotelOrder.getPaymentPrice());
                    cnvHotelOrderDO.setHotelName(briHotelOrder.getHotelName());
                    cnvHotelOrderDO.setRoomName(briHotelOrder.getRoomName());
                    cnvHotelOrderDO.setRoomNums(briHotelOrder.getRoomNums());
                    cnvHotelOrderDO.setArrivalDate(briHotelOrder.getArrivalDate());
                    cnvHotelOrderDO.setDepartureDate(briHotelOrder.getDepartureDate());
                    cnvHotelOrderDO.setInDays(briHotelOrder.getInDays());
                    cnvHotelOrderDO.setCreateTime(briHotelOrder.getCreateTime());
                    cnvHotelOrderDO.setPreOrderMode(briHotelOrder.getPreOrderMode());
                    cnvHotelOrderDO.setCurrency(briHotelOrder.getCurrency());
                    cnvHotelOrderDO.setInNights(briHotelOrder.getInNights());
                    cnvHotelOrderDO.setHotelStars(briHotelOrder.getHotelStars());
                    cnvHotelOrderDO.setCardHolderName(briHotelOrder.getCardHolderName());
                    cnvHotelOrderDO.setHotelType(briHotelOrder.getHotelType());
                    cnvHotelOrderDO.setHotelCity(briHotelOrder.getHotelCity());
                    cnvHotelOrderDO.setPenaltyToCustomer(briHotelOrder.getPenaltyToCustomer());
                    cnvHotelOrderDO.setInvoiceMode(briHotelOrder.getInvoiceMode());
                    cnvHotelOrderDO.setSumServiceCharge(briHotelOrder.getSumServiceCharge());
                    cnvHotelOrderDO.setRelateOtherID(briHotelOrder.getRelateOtherID());
                    cnvHotelOrderDO.setRelateYBZID(briHotelOrder.getRelateYBZID());
                    cnvHotelOrderDO.setApplyOrderNo(briHotelOrder.getApplyOrderNo());
                    cnvHotelOrderDO.setFromType(briHotelOrder.getFromType());
                    cnvHotelOrderDO.setTenant(briHotelOrder.getTenant());
                    cnvHotelOrderDO.setUserId(briHotelOrder.getUserId());
                    cnvHotelOrderDO.setId(briHotelOrder.getId());
                    cnvHotelOrderDO.setPaymentType(briHotelOrder.getPaymentType());
                    cnvHotelOrderDO.setPayType(briHotelOrder.getPayType());
                    cnvHotelOrderDO.setCategory(briHotelOrder.getCategory());
                    cnvHotelOrderDOList.add(cnvHotelOrderDO);
                }
            }
        }
        return cnvHotelOrderDOList;
    }

    private boolean dealWithRefundOrder(BriHotelOrder briHotelOrder) {
        if (ChannelEnum.CLYH.getName().equals(briHotelOrder.getFromType()) || ChannelEnum.FANSCAR.getName().equals(briHotelOrder.getFromType())
                || (ChannelEnum.ZTEITC.getName().equals(briHotelOrder.getFromType()) && !"19".equals(briHotelOrder.getStatusType()))) {
            if ("T".equals(briHotelOrder.getStatusType())) {
                return true;
            }
            BigDecimal refundAmount = new BigDecimal(0);
            Wrapper<BriHotelOrder> hotelWrapper = new EntityWrapper<>();
            hotelWrapper.where("parent_order_no={0}", briHotelOrder.getOrderNo());
            hotelWrapper.and("tenant={0}", briHotelOrder.getTenant());
            hotelWrapper.and("status_type={0}", "T");
            hotelWrapper.and("order_status={0}", "19");
            List<BriHotelOrder> briHotelOrders = briHotelOrderMapper.selectList(hotelWrapper);
            if (!CollectionUtils.isEmpty(briHotelOrders)) {
                for (BriHotelOrder hotelOrder : briHotelOrders) {
                    refundAmount = refundAmount.add(hotelOrder.getPaymentPrice());
                }
                if (new BigDecimal(0).subtract(refundAmount).compareTo(briHotelOrder.getPaymentPrice()) == 0) {
                    return true;
                } else {
                    briHotelOrder.setPaymentPrice(refundAmount.add(briHotelOrder.getPaymentPrice()));
                }
            }
        } else if (ChannelEnum.RTPNR.getName().equals(briHotelOrder.getFromType())) {
            if ("11".equals(briHotelOrder.getOrderStatus()) || "T".equals(briHotelOrder.getStatusType())) {
                if (StringUtils.isEmpty(briHotelOrder.getPenaltyToCustomer())) {
                    return true;
                } else {
                    briHotelOrder.setPaymentPrice(new BigDecimal(briHotelOrder.getPenaltyToCustomer()));
                }
            }
        } else {
            if ("11".equals(briHotelOrder.getOrderStatus()) || "T".equals(briHotelOrder.getStatusType())) {
                return true;
            }
        }
        return false;
    }

    @Override
    public List<BriHotelOrder> getBriHotelOrderByDepartureDate(Map<String, String> params, Date beginDate, Date endDate) {
        // 根据条件查询所有的订单
        Wrapper<BriHotelOrder> hotelOrderWrapper = new EntityWrapper<>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            hotelOrderWrapper.eq(entry.getKey(), entry.getValue());
        }
        hotelOrderWrapper.between("departure_date", beginDate, endDate);
        hotelOrderWrapper.ne(true,"is_note",1);

        return briHotelOrderMapper.selectList(hotelOrderWrapper);
    }

    @Override
    public List<BriHotelOrder> getBriHotelOrder(Map paramas) {
        return briHotelOrderMapper.getBriHotelOrderList(paramas);
    }

    @Override
    public  void updateIsNoteByOrderId(int orderId)
    {
        Map params=new HashMap();
        params.put("id",orderId);
        briHotelOrderMapper.updateIsNoteByOrderId(params);
    }

    @Override
    public void updateIsBxStateByOrderIds(List<Integer> ids,int bxState)
    {
        Map params=new HashMap();
        params.put("ids",ids);
        params.put("bxState",bxState);
        briHotelOrderMapper.updateIsBxStateByOrderIds(params);
    }


    /*
    该接口主要为手工处理异常订单
     */
    @Override
    public List<CnvHotelOrderDO> getCnvFlightOrderDosWithIds(Map<String, String> params,String ids) {
        List<CnvHotelOrderDO> cnvHotelOrderDOList = new ArrayList<>();
        // 根据条件查询所有的订单
        Wrapper<BriHotelOrder> hotelOrderWrapper = new EntityWrapper<>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            hotelOrderWrapper.eq(entry.getKey(), entry.getValue());
        }
        hotelOrderWrapper.ne(true,"is_note",1);
        hotelOrderWrapper.andNew(" id in ("+ids+")");

        List<BriHotelOrder> briHotelOrderList = briHotelOrderMapper.selectList(hotelOrderWrapper);
        ArrayList<String> CompletedOrderStatus = new ArrayList<String>(Arrays.asList("13","14","15","17","20"));
        for (BriHotelOrder briHotelOrder : briHotelOrderList) {
            // 过滤订单状态
            if (StringUtils.isNotBlank(briHotelOrder.getOrderStatus()) && CompletedOrderStatus.contains(briHotelOrder.getOrderStatus())){
                CnvHotelOrderDO cnvHotelOrderDO = new CnvHotelOrderDO();
                convertToCnvHotelOrderDO(briHotelOrder, cnvHotelOrderDO);
                cnvHotelOrderDOList.add(cnvHotelOrderDO);
            }
        }
        return cnvHotelOrderDOList;
    }

    private void convertToCnvHotelOrderDO(BriHotelOrder briHotelOrder, CnvHotelOrderDO cnvHotelOrderDO) {
        if (briHotelOrder != null) {
            cnvHotelOrderDO.setOrderNo(briHotelOrder.getOrderNo());
            cnvHotelOrderDO.setTravelType(briHotelOrder.getTravelType());
            cnvHotelOrderDO.setPublicOrPrivate(briHotelOrder.getPublicOrPrivate());
            cnvHotelOrderDO.setIsDomc(briHotelOrder.getIsDomc());
            cnvHotelOrderDO.setPreiumReason(briHotelOrder.getPreiumReason());
            cnvHotelOrderDO.setPreiumDetail(briHotelOrder.getPreiumDetail());
            cnvHotelOrderDO.setStatusType(briHotelOrder.getStatusType());
            cnvHotelOrderDO.setCreateBy(briHotelOrder.getCreateBy());
            cnvHotelOrderDO.setOrderTime(briHotelOrder.getOrderTime());
            cnvHotelOrderDO.setOrderStatusName(briHotelOrder.getOrderStatusName());
            cnvHotelOrderDO.setPaymentPrice(briHotelOrder.getPaymentPrice());
            cnvHotelOrderDO.setHotelName(briHotelOrder.getHotelName());
            cnvHotelOrderDO.setRoomName(briHotelOrder.getRoomName());
            cnvHotelOrderDO.setRoomNums(briHotelOrder.getRoomNums());
            cnvHotelOrderDO.setArrivalDate(briHotelOrder.getArrivalDate());
            cnvHotelOrderDO.setDepartureDate(briHotelOrder.getDepartureDate());
            cnvHotelOrderDO.setInDays(briHotelOrder.getInDays());
            cnvHotelOrderDO.setCreateTime(briHotelOrder.getCreateTime());
            cnvHotelOrderDO.setPreOrderMode(briHotelOrder.getPreOrderMode());
            cnvHotelOrderDO.setCurrency(briHotelOrder.getCurrency());
            cnvHotelOrderDO.setInNights(briHotelOrder.getInNights());
            cnvHotelOrderDO.setHotelStars(briHotelOrder.getHotelStars());
            cnvHotelOrderDO.setCardHolderName(briHotelOrder.getCardHolderName());
            cnvHotelOrderDO.setHotelType(briHotelOrder.getHotelType());
            cnvHotelOrderDO.setHotelCity(briHotelOrder.getHotelCity());
            cnvHotelOrderDO.setPenaltyToCustomer(briHotelOrder.getPenaltyToCustomer());
            cnvHotelOrderDO.setInvoiceMode(briHotelOrder.getInvoiceMode());
            cnvHotelOrderDO.setSumServiceCharge(briHotelOrder.getSumServiceCharge());
            cnvHotelOrderDO.setRelateOtherID(briHotelOrder.getRelateOtherID());
            cnvHotelOrderDO.setRelateYBZID(briHotelOrder.getRelateYBZID());
            cnvHotelOrderDO.setApplyOrderNo(briHotelOrder.getApplyOrderNo());
            cnvHotelOrderDO.setFromType(briHotelOrder.getFromType());
            cnvHotelOrderDO.setTenant(briHotelOrder.getTenant());
            cnvHotelOrderDO.setUserId(briHotelOrder.getUserId());
            cnvHotelOrderDO.setId(briHotelOrder.getId());
            cnvHotelOrderDO.setPaymentType(briHotelOrder.getPaymentType());
            cnvHotelOrderDO.setCategory(briHotelOrder.getCategory());
            cnvHotelOrderDO.setParentOrderNo(briHotelOrder.getParentOrderNo());
            cnvHotelOrderDO.setPayType(briHotelOrder.getPayType());
        }
    }

    @Override
    public List<BriHotelOrder> getOrdersByRelateYBZId(List<String> ybzIds)
    {
        if(ybzIds!=null&&ybzIds.size()>0) {
            return briHotelOrderMapper.getHotelOrdersByRelateYBZIds(ybzIds);
        } else {
            return  new ArrayList<BriHotelOrder>();
        }
    }

    @Override
    public List<BriHotelOrder> getHotelOrdersByTimeRange(String tenantId, Date begin, Date end) {
        return briHotelOrderMapper.getHotelOrdersByTimeRange(tenantId, begin, end);
    }

    /**
     * 查询酒店订单详情
     * @param params
     * @return
     */
    @Override
    public JSONObject getHotelOrderJson(JSONObject params) {
        return null;
    }


    @Override
    public BriHotelOrder getHotelOrderJson(String tenant, String orderNo) {
        Wrapper<BriHotelOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("tenant", tenant);
        wrapper.eq("order_no", orderNo);
        List<BriHotelOrder> briHotelOrders = briHotelOrderMapper.selectList(wrapper);
        if (briHotelOrders.size() > 0){
            return briHotelOrders.get(0);
        }
        return null;
    }

    @Override
    public CnvHotelOrderDO getBriHotelOrderByOrderNo(String orderNo) {
        CnvHotelOrderDO cnvHotelOrderDO = new CnvHotelOrderDO();
        BriHotelOrder briHotelOrder = briHotelOrderMapper.getBriHotelOrderByOrderNo(orderNo);
        convertToCnvHotelOrderDO(briHotelOrder, cnvHotelOrderDO);
        return cnvHotelOrderDO;
    }
    @Override
    public List<CnvHotelOrderDO> getOrderLikeOrderNo(String orderNo, String fromType, String tenant){
        List<CnvHotelOrderDO> cnvHotelOrderDOList = new ArrayList<>();
        if ("clyh".equals(fromType)){
            Wrapper<BriHotelOrder> wrapper = new EntityWrapper<>();
            wrapper.eq(BriHotelOrder.TENANT, tenant);
            wrapper.like("order_no", orderNo, SqlLike.RIGHT);
            List<BriHotelOrder> hotelOrderList = this.selectList(wrapper);
            for (BriHotelOrder briHotelOrder : hotelOrderList) {
                CnvHotelOrderDO cnvHotelOrderDO = new CnvHotelOrderDO();
                convertToCnvHotelOrderDO(briHotelOrder, cnvHotelOrderDO);
                cnvHotelOrderDOList.add(cnvHotelOrderDO);
            }
        }else {
            CnvHotelOrderDO cnvHotelOrderDO = getBriHotelOrderByOrderNo(orderNo);
            cnvHotelOrderDOList.add(cnvHotelOrderDO);
        }

        return cnvHotelOrderDOList;
    }
    private List<BriHotelOrder> getOrderLikeOrderNoV2(String orderNo, String fromType, String tenant){
        List<BriHotelOrder> cnvHotelOrderDOList = new ArrayList<>();
        if ("clyh".equals(fromType)){
            Wrapper<BriHotelOrder> wrapper = new EntityWrapper<>();
            wrapper.eq(BriHotelOrder.TENANT, tenant);
            wrapper.like("order_no", orderNo, SqlLike.RIGHT);
            List<BriHotelOrder> hotelOrderList = this.selectList(wrapper);
            for (BriHotelOrder briHotelOrder : hotelOrderList) {
                cnvHotelOrderDOList.add(briHotelOrder);
            }
        }else {
            BriHotelOrder cnvHotelOrderDO = briHotelOrderMapper.getBriHotelOrderByOrderNo(orderNo);
            if (cnvHotelOrderDO != null) {
                cnvHotelOrderDOList.add(cnvHotelOrderDO);
            }
        }

        return cnvHotelOrderDOList;
    }

    @Override
    public List<CnvHotelOrderDO> getRelationOrders(String orderNo, String parentNo, String fromType, String tenant) {
        List<CnvHotelOrderDO> orderList = new ArrayList<>();
        boolean isClyh = "clyh".equals(fromType);
        boolean hasPagId = orderNo.split("_").length > 1;
        String passengerId = isClyh && hasPagId ? orderNo.split("_")[1] : "";
        //查询是否有下游单据
        List<BriHotelOrder> hotelOrderList = queryLowerOrders(orderNo, isClyh, tenant,fromType);
        for (BriHotelOrder briHotelOrder : hotelOrderList) {
            String hotelOrderNo = briHotelOrder.getOrderNo();
            // 其退改单的出行人与其订单的出行人身份证一致
            if (isClyh && hasPagId  && !passengerId.equals(hotelOrderNo.split("_")[1])){
                continue;
            }
            fillAndConvert(briHotelOrder, orderList);

            //这个单据可能是改签单，查询下游单据，查询一下这个单据是否有退单
            List<BriHotelOrder> gOrderList = queryLowerOrders(hotelOrderNo, isClyh, tenant,fromType);
            for (BriHotelOrder gHotelOrder : gOrderList) {
                String gHotelOrderNo = gHotelOrder.getOrderNo();
                // 其退改单的出行人与其订单的出行人身份证一致
                if (isClyh && hasPagId  && !passengerId.equals(gHotelOrderNo.split("_")[1])){
                    continue;
                }
                fillAndConvert(gHotelOrder, orderList);

                //这个单据仍然可能是改签单，查询是否有下游单据, 是否有退单
                List<BriHotelOrder> tOrderList = queryLowerOrders(gHotelOrderNo, isClyh, tenant,fromType);
                for (BriHotelOrder tHotelOrder : tOrderList) {
                    String tHotelOrderNo = tHotelOrder.getOrderNo();
                    // 其退改单的出行人与其订单的出行人身份证一致
                    if (isClyh && hasPagId  && !passengerId.equals(tHotelOrderNo.split("_")[1])){
                        continue;
                    }
                    fillAndConvert(tHotelOrder, orderList);
                }
            }

        }
        //查询订单是否有原单
        if (StringUtil.isNotEmpty(parentNo) && (!orderNo.equals(parentNo) && !orderNo.split("_")[0].equals(parentNo))){
            //查询是否有上游单据
            List<CnvHotelOrderDO> cnvHotelOrderDOList = this.getOrderLikeOrderNo(parentNo, fromType, tenant);
            for (CnvHotelOrderDO cnvHotelOrderDO : cnvHotelOrderDOList) {
                String cnvOrderNo = cnvHotelOrderDO.getOrderNo();
                if (StringUtil.isEmpty(cnvOrderNo) || (isClyh && hasPagId  && !passengerId.equals(cnvOrderNo.split("_")[1])) ){
                    continue;
                }
                orderList.add(cnvHotelOrderDO);

                //该原单可能是改签单，查询是否有上游单据。查询是否还有原订单
                String cnvParentOrderNo = cnvHotelOrderDO.getParentOrderNo();
                if (StringUtil.isNotEmpty(cnvParentOrderNo) && !cnvOrderNo.equals(cnvParentOrderNo) && !cnvOrderNo.split("_")[0].equals(cnvParentOrderNo)){
                    List<CnvHotelOrderDO> gCnvHotelOrderList = this.getOrderLikeOrderNo(cnvParentOrderNo, fromType, tenant);
                    for (CnvHotelOrderDO gCnvHotelOrder : gCnvHotelOrderList) {
                        String gCnvOrderNo = gCnvHotelOrder.getOrderNo();
                        if (StringUtil.isEmpty(gCnvOrderNo) || (isClyh && hasPagId  && !passengerId.equals(gCnvOrderNo.split("_")[1])) ){
                            continue;
                        }
                        orderList.add(gCnvHotelOrder);

                        //该原单仍然可能是改签单，查询是否还有上游单据,查询初始单据
                        String oCnvParentOrderNo = gCnvHotelOrder.getParentOrderNo();
                        if (StringUtil.isNotEmpty(oCnvParentOrderNo) && !gCnvOrderNo.equals(oCnvParentOrderNo)){
                            List<CnvHotelOrderDO> oCnvHotelOrderList = this.getOrderLikeOrderNo(oCnvParentOrderNo, fromType, tenant);
                            for (CnvHotelOrderDO oCnvHotelOrder : oCnvHotelOrderList) {
                                String oCnvOrderNo = oCnvHotelOrder.getOrderNo();
                                if (StringUtil.isEmpty(oCnvOrderNo) || (isClyh && hasPagId  && !passengerId.equals(oCnvOrderNo.split("_")[1])) ){
                                    continue;
                                }
                                orderList.add(oCnvHotelOrder);
                            }
                        }

                    }
                }else {
                    // 关联关系可能：退改单与原单关联不是顺序的，退改单的原单号都是原单
                    List<BriHotelOrder> sameLevelOrderList = queryLowerOrders(cnvOrderNo, isClyh, tenant,fromType);
                    if (sameLevelOrderList != null){
                        for (BriHotelOrder sLOrder : sameLevelOrderList) {
                            String slOrderNo = sLOrder.getOrderNo();
                            if (StringUtil.isEmpty(slOrderNo) || (isClyh && hasPagId  && !passengerId.equals(slOrderNo.split("_")[1])) || slOrderNo.equals(orderNo)){
                                continue;
                            }
                            fillAndConvert(sLOrder, orderList);

                        }
                    }
                }
            }

        }
        orderList = distinct(orderList, orderNo);
        return orderList;
    }
    @Override
    public List<BriHotelOrder> getRelationOrdersV2(String orderNo, String parentNo, String fromType, String tenant) {
        List<BriHotelOrder> orderList = new ArrayList<>();
        boolean isClyh = "clyh".equals(fromType);
        boolean hasPagId = orderNo.split("_").length > 1;
        String passengerId = isClyh && hasPagId ? orderNo.split("_")[1] : "";
        //查询是否有下游单据
        List<BriHotelOrder> hotelOrderList = queryLowerOrders(orderNo, isClyh, tenant,fromType);
        if (!CollectionUtils.isEmpty(hotelOrderList)) {
            for (BriHotelOrder briHotelOrder : hotelOrderList) {
                String hotelOrderNo = briHotelOrder.getOrderNo();
                // 其退改单的出行人与其订单的出行人身份证一致
                if (isClyh && hasPagId  && !passengerId.equals(hotelOrderNo.split("_")[1])){
                    continue;
                }
                orderList.add(briHotelOrder);
                //这个单据可能是改签单，查询下游单据，查询一下这个单据是否有退单
                List<BriHotelOrder> gOrderList = queryLowerOrders(hotelOrderNo, isClyh, tenant,fromType);
                for (BriHotelOrder gHotelOrder : gOrderList) {
                    String gHotelOrderNo = gHotelOrder.getOrderNo();
                    // 其退改单的出行人与其订单的出行人身份证一致
                    if (isClyh && hasPagId  && !passengerId.equals(gHotelOrderNo.split("_")[1])){
                        continue;
                    }
                    orderList.add(gHotelOrder);
                    //这个单据仍然可能是改签单，查询是否有下游单据, 是否有退单
                    List<BriHotelOrder> tOrderList = queryLowerOrders(gHotelOrderNo, isClyh, tenant,fromType);
                    for (BriHotelOrder tHotelOrder : tOrderList) {
                        String tHotelOrderNo = tHotelOrder.getOrderNo();
                        // 其退改单的出行人与其订单的出行人身份证一致
                        if (isClyh && hasPagId  && !passengerId.equals(tHotelOrderNo.split("_")[1])){
                            continue;
                        }
                        orderList.add(tHotelOrder);
                    }
                }
            }
        }
        //查询订单是否有原单
        if (StringUtil.isNotEmpty(parentNo) && (!orderNo.equals(parentNo) && !orderNo.split("_")[0].equals(parentNo))){
            //查询是否有上游单据
            List<BriHotelOrder> cnvHotelOrderDOList = this.getOrderLikeOrderNoV2(parentNo, fromType, tenant);
            if (!CollectionUtils.isEmpty(cnvHotelOrderDOList)) {
                for (BriHotelOrder cnvHotelOrderDO : cnvHotelOrderDOList) {
                    String cnvOrderNo = cnvHotelOrderDO.getOrderNo();
                    if (StringUtil.isEmpty(cnvOrderNo) || (isClyh && hasPagId  && !passengerId.equals(cnvOrderNo.split("_")[1])) ){
                        continue;
                    }
                    orderList.add(cnvHotelOrderDO);
                    //该原单可能是改签单，查询是否有上游单据。查询是否还有原订单
                    String cnvParentOrderNo = cnvHotelOrderDO.getParentOrderNo();
                    if (StringUtil.isNotEmpty(cnvParentOrderNo) && !cnvOrderNo.equals(cnvParentOrderNo) && !cnvOrderNo.split("_")[0].equals(cnvParentOrderNo)){
                        List<BriHotelOrder> gCnvHotelOrderList = this.getOrderLikeOrderNoV2(cnvParentOrderNo, fromType, tenant);
                        for (BriHotelOrder gCnvHotelOrder : gCnvHotelOrderList) {
                            String gCnvOrderNo = gCnvHotelOrder.getOrderNo();
                            if (StringUtil.isEmpty(gCnvOrderNo) || (isClyh && hasPagId  && !passengerId.equals(gCnvOrderNo.split("_")[1])) ){
                                continue;
                            }
                            orderList.add(gCnvHotelOrder);
                            //该原单仍然可能是改签单，查询是否还有上游单据,查询初始单据
                            String oCnvParentOrderNo = gCnvHotelOrder.getParentOrderNo();
                            if (StringUtil.isNotEmpty(oCnvParentOrderNo) && !gCnvOrderNo.equals(oCnvParentOrderNo)){
                                List<BriHotelOrder> oCnvHotelOrderList = this.getOrderLikeOrderNoV2(oCnvParentOrderNo, fromType, tenant);
                                for (BriHotelOrder oCnvHotelOrder : oCnvHotelOrderList) {
                                    String oCnvOrderNo = oCnvHotelOrder.getOrderNo();
                                    if (StringUtil.isEmpty(oCnvOrderNo) || (isClyh && hasPagId  && !passengerId.equals(oCnvOrderNo.split("_")[1])) ){
                                        continue;
                                    }
                                    orderList.add(oCnvHotelOrder);
                                }
                            }
                        }
                    }else {
                        // 关联关系可能：退改单与原单关联不是顺序的，退改单的原单号都是原单
                        List<BriHotelOrder> sameLevelOrderList = queryLowerOrders(cnvOrderNo, isClyh, tenant,fromType);
                        if (sameLevelOrderList != null){
                            for (BriHotelOrder sLOrder : sameLevelOrderList) {
                                String slOrderNo = sLOrder.getOrderNo();
                                if (StringUtil.isEmpty(slOrderNo) || (isClyh && hasPagId  && !passengerId.equals(slOrderNo.split("_")[1])) || slOrderNo.equals(orderNo)){
                                    continue;
                                }
                                orderList.add(sLOrder);
                            }
                        }
                    }
                }
            }
        }
        orderList = distinctV2(orderList, orderNo);
        return orderList;
    }

    @Override
    public JSONArray getHotelOrders(String userId, String bxState, String beginDate, String endDate, String tenant, Map<String, List<Map<String, String>>> canBeSeen) {
        List<BriHotelOrder> briHotelOrderList = this.getHotelOrdersByBxState(userId, bxState, beginDate, endDate, tenant, canBeSeen);
        return getOrdersDetails(briHotelOrderList, true);
    }


    @Override
    public JSONArray getHotelOrders(String tenant, String orderNo) {
        JSONArray result = new JSONArray();
        Wrapper<BriHotelOrder> wrapper = new EntityWrapper<>();
        wrapper.eq(BriHotelOrder.TENANT, tenant);
        wrapper.eq(BriHotelOrder.ORDER_NO, orderNo);
        BriHotelOrder briHotelOrder = this.selectOne(wrapper);
        List<BriHotelOrder> orderList = new ArrayList<>();
        if (briHotelOrder != null){
            List<BriHotelOrder> relationOrderList = getRelationOrdersV2(briHotelOrder.getOrderNo(), briHotelOrder.getParentOrderNo(), briHotelOrder.getFromType(), tenant);
            orderList.addAll(relationOrderList);
            orderList.add(briHotelOrder);
            result.addAll(getOrdersDetails(orderList, false));
        }
        return result;
    }

    private JSONArray getOrdersDetails(List<BriHotelOrder> briHotelOrderList, Boolean isFilter){
        JSONArray hotelOrderArr = new JSONArray();
        Iterator<BriHotelOrder> iterator = briHotelOrderList.iterator();
        while (iterator.hasNext()) {
            BriHotelOrder briHotelOrder = iterator.next();
            String orderNo = briHotelOrder.getOrderNo();
            JSONObject orderJSON = objToJSONObject(briHotelOrder);

            if (briHotelOrder.getDepartureDate() == null || new Date().before(briHotelOrder.getDepartureDate())) {
                // 未出行
                if (isFilter){
                    iterator.remove();
                    continue;
                }
            }
            //酒店房间信息 hotelRooms
            List<BriHotelRoom> roomList = briHotelRoomService.getBriHotelRoom(orderNo);
            JSONArray roomArr = listToJSONArray(roomList);
            orderJSON.put("hotelRooms", roomArr);
            //发票信息
            List<InvoiceRelationship> relationshipList = relationshipService.getRelationshipsByOrderNo(orderNo);
            JSONArray relationArr = listToJSONArray(relationshipList);
            orderJSON.put("invoices", relationArr);

            hotelOrderArr.add(orderJSON);
        }

        return hotelOrderArr;
    }

    @Override
    public List<BriHotelOrder> getHotelOrdersByBxState(String userId, String bxState, String beginDate, String endDate, String tenant, Map<String, List<Map<String, String>>> canBeSeen){
        return briHotelOrderMapper.getOrdersByBxState(userId, bxState, beginDate, endDate, tenant, canBeSeen);
    }

    /**
     * 将对象转成JSONObject
     * @param object
     * @return
     */
    private JSONObject objToJSONObject(Object object){
        String jsonString = JSONObject.toJSONString(object);
        return JSONObject.parseObject(jsonString);
    }

    /**
     * 将list转成JSONArray
     * @param list
     * @return
     */
    private JSONArray listToJSONArray(List list){
        String jsonString = JSONArray.toJSONString(list);
        return JSONArray.parseArray(jsonString);
    }
    private List<BriHotelOrder> queryLowerOrders(String orderNo, boolean isClyh, String tenant,String fromType) {
        String[] orderSplilt = orderNo.split("_");
        //查看该订单是否是其他订单的原单
        Wrapper<BriHotelOrder> wrapper = new EntityWrapper<>();
        wrapper.eq(BriHotelOrder.TENANT, tenant);
        if (isClyh){
            wrapper.like("parent_order_no", orderSplilt[0], SqlLike.RIGHT);
        }else {
            wrapper.eq("parent_order_no", orderNo);
        }
        List<BriHotelOrder> rsList = new ArrayList<>();
        List<BriHotelOrder> hotelOrderList = this.selectList(wrapper);
        //携程大客户退改签 和 出票 orderNo相同，没有用parent_order_no关联
        if (ChannelEnum.CTRIPBC.getName().equalsIgnoreCase(fromType)) {
            wrapper = new EntityWrapper<>();
            wrapper.eq(BriHotelOrder.TENANT, tenant);
            wrapper.like("order_no", orderSplilt[0], SqlLike.RIGHT);
            hotelOrderList = this.selectList(wrapper);
        }
        if (!CollectionUtils.isEmpty(hotelOrderList)) {
            for (BriHotelOrder briHotelOrder : hotelOrderList) {
                if (orderNo.equals(briHotelOrder.getOrderNo())){
                    continue;
                }
                rsList.add(briHotelOrder);
            }
        }
        return rsList;
    }

    private void fillAndConvert(BriHotelOrder briHotelOrder, List<CnvHotelOrderDO> orderList){
        CnvHotelOrderDO cnvHotelOrderDO = new CnvHotelOrderDO();
        convertToCnvHotelOrderDO(briHotelOrder, cnvHotelOrderDO);
        orderList.add(cnvHotelOrderDO);
    }
    private static List<CnvHotelOrderDO> distinct(List<CnvHotelOrderDO> cnvFlightOrderDOList, String orderNo) {
        HashMap<String, CnvHotelOrderDO> map = new HashMap<>();
        for (CnvHotelOrderDO cnvHotelOrderDO : cnvFlightOrderDOList) {
            map.put(cnvHotelOrderDO.getOrderNo(), cnvHotelOrderDO);
        }
        cnvFlightOrderDOList = new ArrayList<CnvHotelOrderDO>();
        for (Map.Entry<String, CnvHotelOrderDO> entry : map.entrySet()) {
            if (!orderNo.equals(entry.getKey())){
                cnvFlightOrderDOList.add(entry.getValue());
            }
        }
        return cnvFlightOrderDOList;
    }
    private static List<BriHotelOrder> distinctV2(List<BriHotelOrder> cnvFlightOrderDOList, String orderNo) {
        HashMap<String, BriHotelOrder> map = new HashMap<>();
        for (BriHotelOrder briHotelOrder : cnvFlightOrderDOList) {
            map.put(briHotelOrder.getOrderNo(), briHotelOrder);
        }
        cnvFlightOrderDOList = new ArrayList<BriHotelOrder>();
        for (Map.Entry<String, BriHotelOrder> entry : map.entrySet()) {
            if (!orderNo.equals(entry.getKey())){
                cnvFlightOrderDOList.add(entry.getValue());
            }
        }
        return cnvFlightOrderDOList;
    }
}
